﻿using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.VirtualFileSystem;
using Xms.Abp.Authorization;
using Xms.Abp.Features.Localization;
using Xms.Abp.Modularity;
using Xms.Abp.Validation;

namespace Xms.Abp.Features;

[DependsOn(
    typeof(AbpLocalizationModule),
    typeof(AbpMultiTenancyModule),
    typeof(XmsAbpValidationModule),
    typeof(XmsAbpAuthorizationAbstractionsModule),
    typeof(XmsAbpValidationModule)
    )]
public class XmsAbpFeaturesModule : XmsModule
{
    public override void PreConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.OnRegistred(FeatureInterceptorRegistrar.RegisterIfNeeded);
        AutoAddDefinitionProviders(context.Services);
    }

    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.Configure<FeatureOptions>(options =>
        {
            options.ValueProviders.Add<DefaultValueFeaturesValueProvider>();
            options.ValueProviders.Add<EditionFeaturesValueProvider>();
            options.ValueProviders.Add<TenantFeaturesValueProvider>();
        });

        Configure<AbpVirtualFileSystemOptions>(options =>
        {
            options.FileSets.AddEmbedded<FeaturesResource>();
        });

        Configure<AbpLocalizationOptions>(options =>
        {
            options.Resources
                .Add<FeaturesResource>("en")
                .AddVirtualJson("/Features/Localization/Resources");
        });

        Configure<AbpExceptionLocalizationOptions>(options =>
        {
            options.MapCodeNamespace("Xms.Features", typeof(FeaturesResource));
        });
    }

    private static void AutoAddDefinitionProviders(IServiceCollection services)
    {
        var definitionProviders = new List<Type>();

        services.OnRegistred(context =>
        {
            if (typeof(IFeaturesDefinitionProvider).IsAssignableFrom(context.ImplementationType))
            {
                definitionProviders.Add(context.ImplementationType);
            }
        });

        services.Configure<FeatureOptions>(options =>
        {
            options.DefinitionProviders.AddIfNotContains(definitionProviders);
        });
    }
}
